<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>实时摄像头情绪检测</title>
    <link rel="stylesheet" href="/static/css/style.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
    <style>
        body, html {
            height: 100%;
            margin: 0;
            padding: 0;
            min-height: 100vh;
            background: url('/static/images/camera.png') no-repeat center center fixed;
            background-size: cover;
        }
        .camera-main {
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            padding: 20px;
            box-sizing: border-box;
        }
        .camera-card {
            background: rgba(255, 255, 255, 0.85);
            border-radius: 16px;
            box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.05), 0 8px 10px -6px rgba(0, 0, 0, 0.02);
            padding: 32px;
            max-width: 800px;
            width: 100%;
            margin: 24px auto;
            text-align: center;
            transition: all 0.3s ease;
        }
        .camera-card:hover {
            transform: translateY(-2px);
            box-shadow: 0 15px 30px -8px rgba(0, 0, 0, 0.08), 0 10px 15px -6px rgba(0, 0, 0, 0.04);
        }
        .camera-title {
            font-size: 2.4rem;
            font-weight: bold;
            color: #2d3a4b;
            margin-bottom: 24px;
            letter-spacing: 2px;
            text-shadow: 0 2px 8px rgba(255, 255, 255, 0.7);
        }
        #result-img {
            border-radius: 12px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.12);
            margin-bottom: 18px;
            max-width: 100%;
            transition: transform 0.3s ease;
        }
        #result-img:hover {
            transform: scale(1.02);
        }
        .back-btn {
            margin-top: 32px;
            background: linear-gradient(90deg, #43e97b 0%, #38f9d7 100%);
            color: #fff;
            border: none;
            border-radius: 12px;
            padding: 14px 42px;
            font-size: 1.2rem;
            font-weight: bold;
            cursor: pointer;
            box-shadow: 0 4px 15px rgba(67,233,123,0.2);
            transition: all 0.3s ease;
            text-decoration: none;
            display: inline-block;
        }
        .back-btn:hover {
            background: linear-gradient(90deg, #38f9d7 0%, #43e97b 100%);
            transform: translateY(-2px);
            box-shadow: 0 6px 20px rgba(67,233,123,0.25);
            color: #fff;
            text-decoration: none;
        }
        @media (max-width: 768px) {
            .camera-card { 
                padding: 24px 16px;
                margin: 20px 10px;
            }
            .camera-title {
                font-size: 1.8rem;
            }
            .back-btn {
                padding: 12px 32px;
                font-size: 1.1rem;
            }
        }
        
        /* 添加加载状态指示器样式 */
        .loading-indicator {
            position: absolute;
            top: 10px;
            right: 10px;
            padding: 5px 10px;
            background: rgba(0, 0, 0, 0.5);
            color: white;
            border-radius: 5px;
            font-size: 14px;
            display: none;
        }
        
        /* 添加错误提示样式 */
        .error-message {
            color: #e74c3c;
            margin-top: 10px;
            padding: 10px;
            background: rgba(231, 76, 60, 0.1);
            border-radius: 5px;
            display: none;
        }

        /* 聊天功能样式 */
        #chat-popup {
            position: fixed;
            right: 32px;
            bottom: 100px;
            width: 630px;
            max-width: 98vw;
            height: 480px;
            max-height: 90vh;
            background: #fff;
            border-radius: 16px;
            display: none;
            flex-direction: column;
            z-index: 10000;
            overflow: hidden;
            animation: popupIn 0.18s;
        }

        @keyframes popupIn {
            from { transform: translateY(40px); opacity: 0; }
            to { transform: translateY(0); opacity: 1; }
        }

        .container { 
            max-width: 600px; 
            margin: 0; 
            background: #fff;
            border-radius: 12px;
            padding: 0; 
            position: relative; 
        }

        #chat-box {
            width: 100%;
            height: 400px;
            border: none;
            background: #fff;
            overflow-y: auto;
            padding: 16px;
            margin-bottom: 10px;
            display: flex;
            flex-direction: column;
            gap: 12px;
        }

        .message-row {
            display: flex;
            align-items: flex-end;
        }

        .message-row.user {
            justify-content: flex-end;
        }

        .message-row.assistant {
            justify-content: flex-start;
        }

        .avatar {
            width: 38px;
            height: 38px;
            border-radius: 50%;
            object-fit: cover;
            margin: 0 12px;
            background: #fff;
        }

        .message-row.user .avatar {
            order: 2;
            margin-left: 12px;
            margin-right: 0;
        }

        .message-row.assistant .avatar {
            order: 0;
            margin-right: 12px;
            margin-left: 0;
        }

        .bubble {
            max-width: calc(65% - 50px);
            padding: 12px 18px;
            border-radius: 18px;
            font-size: 16px;
            line-height: 1.6;
            word-break: break-word;
        }

        .bubble.user {
            background: #e6f0ff;
            color: #222;
            border-bottom-right-radius: 6px;
        }

        .bubble.assistant {
            background: #fff;
            color: #222;
            border-bottom-left-radius: 6px;
        }

        #input-area {
            display: flex;
            gap: 8px;
            padding: 0 16px 16px 16px;
            background: #fff;
        }

        #user-input {
            flex: 1;
            padding: 10px;
            border-radius: 8px;
            border: 1px solid #ccc;
            font-size: 16px;
            background: #fff;
        }

        #send-btn {
            padding: 10px 22px;
            border-radius: 8px;
            border: none;
            background: #4e8cff;
            color: #fff;
            font-size: 16px;
            cursor: pointer;
            transition: background 0.2s;
        }

        #send-btn:hover {
            background: #2563d8;
        }

        #chat-float-btn {
            position: fixed;
            right: 32px;
            bottom: 32px;
            width: 220px;
            height: 320px;
            background: transparent;
            box-shadow: none;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            z-index: 9999;
            padding: 0;
            border: none;
        }

        #three-avatar {
            width: 220px;
            height: 320px;
        }

        #three-avatar canvas {
            width: 100% !important;
            height: 100% !important;
            border-radius: 0;
            display: block;
            background: transparent;
        }

        .bubble-text {
            position: absolute;
            left: 50%;
            top: 80px;
            transform: translateX(-50%);
            background: #fff;
            color: #7a5fa1;
            border-radius: 22px;
            padding: 14px 26px;
            font-size: 17px;
            font-family: 'Segoe UI Rounded', 'HarmonyOS Sans', 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
            line-height: 1.7;
            white-space: nowrap;
            pointer-events: none;
            z-index: 10;
            border: 1.5px solid #b3d8ff;
            opacity: 0.98;
            transition: opacity 0.3s;
            box-sizing: border-box;
        }
    </style>
</head>
<body>
<div class="camera-main">
    <div class="camera-card">
        <div class="camera-title"><i class="fa-solid fa-video"></i> 实时摄像头情绪检测</div>
        <div style="position: relative;">
            <img id="result-img" width="640" height="480">
            <div id="loading" class="loading-indicator">处理中...</div>
        </div>
        <div id="error" class="error-message"></div>
        <canvas id="canvas" width="640" height="480" style="display:none;"></canvas>
        <a href="/" class="back-btn"><i class="fa-solid fa-house"></i> 返回首页</a>
    </div>
</div>

<!-- 聊天功能 -->
{% if session.get('user_id') %}
<div id="chat-float-btn" title="AI 聊天">
    <div id="three-avatar" style="width:220px;height:320px; position:relative;">
        <div id="bubble-text" class="bubble-text"></div>
    </div>
</div>

<div id="chat-popup">
    <div class="container">
        <div id="chat-box"></div>
        <div id="input-area">
            <input type="text" id="user-input" placeholder="请输入..." autofocus>
            <button id="send-btn">发送</button>
        </div>
    </div>
</div>
{% endif %}

<script>
    // 配置参数
    const CONFIG = {
        processingInterval: 200,    // 处理间隔时间（毫秒）
        imageQuality: 0.6,         // 图片质量（0-1）
        maxImageWidth: 480,        // 最大图片宽度
        maxRetries: 3              // 最大重试次数
    };

    // 状态变量
    let isProcessing = false;
    let lastProcessTime = 0;
    let errorCount = 0;
    let processingTimeout = null;

    // DOM 元素
    const video = document.createElement('video');
    const canvas = document.getElementById('canvas');
    const resultImg = document.getElementById('result-img');
    const loadingIndicator = document.getElementById('loading');
    const errorMessage = document.getElementById('error');

    // 设置视频属性
    video.setAttribute('autoplay', true);
    video.setAttribute('playsinline', true); // 对iOS很重要
    video.setAttribute('width', CONFIG.maxImageWidth);
    video.setAttribute('height', CONFIG.maxImageWidth * 3/4);
    video.style.display = 'none';
    document.body.appendChild(video);

    // 调整canvas大小
    canvas.width = CONFIG.maxImageWidth;
    canvas.height = CONFIG.maxImageWidth * 3/4;

    // 打开摄像头
    navigator.mediaDevices.getUserMedia({ 
        video: { 
            width: { ideal: CONFIG.maxImageWidth },
            height: { ideal: CONFIG.maxImageWidth * 3/4 },
            facingMode: "user"
        } 
    })
    .then(stream => {
        video.srcObject = stream;
        video.onloadedmetadata = () => {
            video.play();
            requestAnimationFrame(detectLoop);
        };
    })
    .catch(err => {
        console.error('无法访问摄像头:', err);
        showError('无法访问摄像头，请检查权限设置');
    });

    // 显示错误信息
    function showError(message) {
        errorMessage.textContent = message;
        errorMessage.style.display = 'block';
        setTimeout(() => {
            errorMessage.style.display = 'none';
        }, 3000);
    }

    // 检测循环
    function detectLoop() {
        const now = Date.now();
        if (!isProcessing && (now - lastProcessTime) >= CONFIG.processingInterval) {
            detectFrame();
        }
        requestAnimationFrame(detectLoop);
    }

    // 处理单帧
    function detectFrame() {
        if (isProcessing) return;
        
        isProcessing = true;
        lastProcessTime = Date.now();
        loadingIndicator.style.display = 'block';

        // 清除之前的超时
        if (processingTimeout) {
            clearTimeout(processingTimeout);
        }

        // 设置新的超时
        processingTimeout = setTimeout(() => {
            isProcessing = false;
            loadingIndicator.style.display = 'none';
        }, 5000); // 5秒超时

        // 绘制并压缩图像
        const ctx = canvas.getContext('2d');
        ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
        
        canvas.toBlob(blob => {
            const formData = new FormData();
            formData.append('file', blob, 'camera.jpg');

            fetch('/detect/camera_upload', {
                method: 'POST',
                body: formData
            })
            .then(res => {
                if (!res.ok) throw new Error('网络响应错误');
                return res.json();
            })
            .then(data => {
                if (data.success && data.image_url) {
                    resultImg.src = data.image_url + '?t=' + Date.now();
                    errorCount = 0; // 重置错误计数
                } else {
                    throw new Error('处理失败');
                }
            })
            .catch(error => {
                console.error('处理错误:', error);
                errorCount++;
                if (errorCount >= CONFIG.maxRetries) {
                    showError('连续处理失败，请检查网络连接');
                }
            })
            .finally(() => {
                isProcessing = false;
                loadingIndicator.style.display = 'none';
                clearTimeout(processingTimeout);
            });
        }, 'image/jpeg', CONFIG.imageQuality);
    }
</script>

{% if session.get('user_id') %}
<script src="/static/js/three.min.js"></script>
<script src="/static/js/GLTFLoader.js"></script>
<script src="/static/js/OrbitControls.js"></script>
<script>
    const chatBox = document.getElementById('chat-box');
    const userInput = document.getElementById('user-input');
    const sendBtn = document.getElementById('send-btn');
    const chatFloatBtn = document.getElementById('chat-float-btn');
    const chatPopup = document.getElementById('chat-popup');
    const avatarContainer = document.getElementById('three-avatar');

    chatFloatBtn.onclick = function(e) {
        e.stopPropagation();
        chatPopup.style.display = chatPopup.style.display === 'flex' ? 'none' : 'flex';
        chatPopup.style.flexDirection = 'column';
        if (chatPopup.style.display === 'flex') {
            setTimeout(() => { userInput.focus(); }, 200);
        }
    };

    chatPopup.onclick = function(e) {
        e.stopPropagation();
    };

    document.addEventListener('click', function() {
        if (chatPopup.style.display === 'flex') {
            chatPopup.style.display = 'none';
        }
    });

    function appendMessage(role, text) {
        const row = document.createElement('div');
        row.className = 'message-row ' + role;
        const avatar = document.createElement('img');
        avatar.className = 'avatar';
        avatar.src = role === 'user'
            ? '/static/images/people_img.jpg'
            : '/static/images/chat_img.png';
        avatar.alt = role === 'user' ? '用户头像' : 'AI头像';
        const bubble = document.createElement('div');
        bubble.className = 'bubble ' + role;
        bubble.textContent = text;
        if (role === 'user') {
            row.appendChild(bubble);
            row.appendChild(avatar);
        } else {
            row.appendChild(avatar);
            row.appendChild(bubble);
        }
        chatBox.appendChild(row);
        chatBox.scrollTop = chatBox.scrollHeight;
    }

    sendBtn.onclick = async function() {
        const text = userInput.value.trim();
        if (!text) return;
        appendMessage('user', text);
        userInput.value = '';
        appendMessage('assistant', '思考中...');

        const res = await fetch('/chat', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ message: text })
        });
        const data = await res.json();
        chatBox.lastChild.querySelector('.bubble').textContent = data.reply;
    };

    userInput.addEventListener('keydown', function(e) {
        if (e.key === 'Enter') sendBtn.click();
    });

    // Three.js 3D数字人
    let renderer, scene, camera, mixer, clock, model, controls;

    function init3DAvatar() {
        scene = new THREE.Scene();
        camera = new THREE.PerspectiveCamera(45, 220/320, 0.1, 100);
        camera.position.set(0, 1.2, 4.5);

        renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
        renderer.setSize(220, 320);
        renderer.setClearColor(0x000000, 0);
        avatarContainer.appendChild(renderer.domElement);

        const light = new THREE.DirectionalLight(0xffffff, 1);
        light.position.set(0, 2, 2);
        scene.add(light);
        scene.add(new THREE.AmbientLight(0xffffff, 0.7));

        controls = new THREE.OrbitControls(camera, renderer.domElement);
        controls.enableZoom = false;
        controls.enablePan = false;
        controls.autoRotate = true;
        controls.autoRotateSpeed = 1.0;

        const loader = new THREE.GLTFLoader();
        loader.load('/static/images/digital_human.glb', function(gltf) {
            model = gltf.scene;
            model.scale.set(0.3, 0.3, 0.3);
            model.position.set(0.5, -1.5, 0);
            scene.add(model);

            if (gltf.animations && gltf.animations.length > 0) {
                mixer = new THREE.AnimationMixer(model);
                gltf.animations.forEach((clip) => {
                    mixer.clipAction(clip).play();
                });
            }
        });

        clock = new THREE.Clock();
        animate();
    }

    function animate() {
        requestAnimationFrame(animate);
        if (mixer) mixer.update(clock.getDelta());
        if (controls) controls.update();
        if (model) {
            model.rotation.y += 0.02;
        }
        renderer.render(scene, camera);
    }

    init3DAvatar();

    const bubbleTexts = [
        "你好呀",
        "有什么情绪方面的问题想和我聊聊吗？",
        "我可以陪你谈心哦~"
    ];
    let bubbleIndex = 0;
    const bubbleDiv = document.getElementById('bubble-text');

    function showNextBubble() {
        bubbleDiv.textContent = bubbleTexts[bubbleIndex];
        bubbleIndex = (bubbleIndex + 1) % bubbleTexts.length;
    }
    showNextBubble();
    setInterval(showNextBubble, 2500);
</script>
{% endif %}
</body>
</html> 